{
 "cells": [
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "# 通用的方式：Agent->AgentExecutor\n",
    "## 1、 FUNCTION_CALL的模式"
   ],
   "id": "899cf4bf356e3318"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-05T06:12:17.403211Z",
     "start_time": "2025-08-05T06:12:12.346507Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from langchain_openai import ChatOpenAI\n",
    "import dotenv\n",
    "from langchain_core.tools import Tool\n",
    "import os\n",
    "#1、提供工具\n",
    "# 1.导入相关包\n",
    "from langchain.agents import AgentExecutor, create_tool_calling_agent, create_react_agent\n",
    "from langchain_community.tools.tavily_search import TavilySearchResults\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "\n",
    "# 2.定义搜索化工具\n",
    "# ① 设置 TAVILY_API 密钥\n",
    "os.environ[\"TAVILY_API_KEY\"] = \"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\"  # 需要替换为你的 Tavily API 密钥\n",
    "\n",
    "# ② 定义搜索工具\n",
    "search = TavilySearchResults(max_results=1)\n",
    "search_tool = Tool(\n",
    "    name=\"search_tool\",\n",
    "    func=search.run,\n",
    "    description=\"用于互联网信息的检索\"\n",
    ")\n",
    "\n",
    "#2、提供工具集\n",
    "tools = [search_tool]\n",
    "\n",
    "#3、提供大模型\n",
    "dotenv.load_dotenv()\n",
    "\n",
    "os.environ['OPENAI_API_KEY'] = os.getenv(\"OPENAI_API_KEY\")\n",
    "os.environ['OPENAI_BASE_URL'] = os.getenv(\"OPENAI_BASE_URL\")\n",
    "llm = ChatOpenAI(\n",
    "    model=\"gpt-4o-mini\",\n",
    "    temperature=0,  #表示回答更准确(减少随机性)\n",
    ")\n",
    "#4、提供提示词模板 （明显相对于传统模式的区别）\n",
    "prompt_template = ChatPromptTemplate.from_messages([\n",
    "    (\"system\", \"你是一个人工智能的助手，必要时根据用户的需求，即时调用TavilySearch工具进行网络搜索\"),\n",
    "    (\"human\", \"我的问题是：{question}\"),\n",
    "    (\"system\", \"{agent_scratchpad}\")  #必须在提示词模板中提供agent_scratchpad参数。\n",
    "])\n",
    "\n",
    "#5、创建Agent\n",
    "agent = create_tool_calling_agent(\n",
    "    llm=llm,\n",
    "    tools=tools,\n",
    "    prompt=prompt_template,\n",
    ")\n",
    "\n",
    "#6、创建AgentExecutor\n",
    "agent_executor = AgentExecutor(\n",
    "    agent=agent,\n",
    "    tools=tools,\n",
    "    verbose=True,  #显示详情\n",
    ")\n",
    "\n",
    "#7、调用\n",
    "agent_executor.invoke({\"question\": \"今年9月3号北京会有阅兵吗？\"})\n"
   ],
   "id": "ca29a07ab85138c3",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001B[1m> Entering new AgentExecutor chain...\u001B[0m\n",
      "\u001B[32;1m\u001B[1;3m\n",
      "Invoking: `search_tool` with `2023年9月3号 北京 阅兵`\n",
      "\n",
      "\n",
      "\u001B[0m\u001B[36;1m\u001B[1;3m[{'title': '快讯：9月3日北京天安门广场将举行阅兵 - 中国政府网', 'url': 'https://www.gov.cn/yaowen/liebiao/202506/content_7029176.htm', 'content': '# å¿«è®¯ï¼\\x9a9æ\\x9c\\x883æ\\x97¥å\\x8c\\x97äº¬å¤©å®\\x89é\\x97¨å¹¿å\\x9cºå°\\x86ä¸¾è¡\\x8cé\\x98\\x85å\\x85µ\\n\\næ\\x96°å\\x8d\\x8eç¤¾å¿«è®¯ï¼\\x9aè®°è\\x80\\x85ä»\\x8eå\\x9b½æ\\x96°å\\x8a\\x9eæ\\x96°é\\x97»å\\x8f\\x91å¸\\x83ä¼\\x9aè\\x8e·æ\\x82\\x89ï¼\\x8c9æ\\x9c\\x883æ\\x97¥ä¸\\x8aå\\x8d\\x88ï¼\\x8cå\\x8c\\x97äº¬å¤©å®\\x89é\\x97¨å¹¿å\\x9cºå°\\x86ä¸¾è¡\\x8cçºªå¿µä¸\\xadå\\x9b½äººæ°\\x91æ\\x8a\\x97æ\\x97¥æ\\x88\\x98äº\\x89æ\\x9a¨ä¸\\x96ç\\x95\\x8cå\\x8f\\x8dæ³\\x95è¥¿æ\\x96¯æ\\x88\\x98äº\\x89è\\x83\\x9cå\\x88©80å\\x91¨å¹´å¤§ä¼\\x9aï¼\\x8cå\\x8c\\x85æ\\x8b¬æ£\\x80é\\x98\\x85é\\x83¨é\\x98\\x9fã\\x80\\x82\\n\\nä¸»å\\x8a\\x9eå\\x8d\\x95ä½\\x8dï¼\\x9aå\\x9b½å\\x8a¡é\\x99¢å\\x8a\\x9eå\\x85¬å\\x8e\\x85ã\\x80\\x80è¿\\x90è¡\\x8cç»´æ\\x8a¤å\\x8d\\x95ä½\\x8dï¼\\x9aä¸\\xadå\\x9b½æ\\x94¿åº\\x9cç½\\x91è¿\\x90è¡\\x8cä¸\\xadå¿\\x83\\n\\nç\\x89\\x88æ\\x9d\\x83æ\\x89\\x80æ\\x9c\\x89ï¼\\x9aä¸\\xadå\\x9b½æ\\x94¿åº\\x9cç½\\x91ã\\x80\\x80ä¸\\xadæ\\x96\\x87å\\x9f\\x9få\\x90\\x8dï¼\\x9aä¸\\xadå\\x9b½æ\\x94¿åº\\x9cç½\\x91.æ\\x94¿å\\x8a¡ [...] ç½\\x91ç«\\x99æ \\x87è¯\\x86ç \\x81bm01000001ã\\x80\\x80äº¬ICPå¤\\x8705070218å\\x8f·ã\\x80\\x80äº¬å\\x85¬ç½\\x91å®\\x89å¤\\x8711010202000001å\\x8f·\\n\\nä¸\\xadå\\x9b½æ\\x94¿åº\\x9cç½\\x91å¾®å\\x8d\\x9aã\\x80\\x81å¾®ä¿¡\\n\\nä¸»å\\x8a\\x9eå\\x8d\\x95ä½\\x8dï¼\\x9aå\\x9b½å\\x8a¡é\\x99¢å\\x8a\\x9eå\\x85¬å\\x8e\\x85ã\\x80\\x80è¿\\x90è¡\\x8cç»´æ\\x8a¤å\\x8d\\x95ä½\\x8dï¼\\x9aä¸\\xadå\\x9b½æ\\x94¿åº\\x9cç½\\x91è¿\\x90è¡\\x8cä¸\\xadå¿\\x83\\n\\nç\\x89\\x88æ\\x9d\\x83æ\\x89\\x80æ\\x9c\\x89ï¼\\x9aä¸\\xadå\\x9b½æ\\x94¿åº\\x9cç½\\x91ã\\x80\\x80ä¸\\xadæ\\x96\\x87å\\x9f\\x9få\\x90\\x8dï¼\\x9aä¸\\xadå\\x9b½æ\\x94¿åº\\x9cç½\\x91.æ\\x94¿å\\x8a¡\\n\\nç½\\x91ç«\\x99æ \\x87è¯\\x86ç \\x81bm01000001\\n\\näº¬ICPå¤\\x8705070218å\\x8f·ã\\x80\\x80äº¬å\\x85¬ç½\\x91å®\\x89å¤\\x8711010202000001å\\x8f·', 'score': 0.7366474}]\u001B[0m\u001B[32;1m\u001B[1;3m是的，2023年9月3日北京将举行阅兵仪式。有关详细信息，可以参考中国政府网的相关报道：[快讯：9月3日北京天安门广场将举行阅兵](https://www.gov.cn/yaowen/liebiao/202506/content_7029176.htm)。\u001B[0m\n",
      "\n",
      "\u001B[1m> Finished chain.\u001B[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'question': '今年9月3号北京会有阅兵吗？',\n",
       " 'output': '是的，2023年9月3日北京将举行阅兵仪式。有关详细信息，可以参考中国政府网的相关报道：[快讯：9月3日北京天安门广场将举行阅兵](https://www.gov.cn/yaowen/liebiao/202506/content_7029176.htm)。'}"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 4
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "1，导入工具包和设置环境包\n",
    "2，定义搜索工具\n",
    "3，准备工具列表\n",
    "4，配置AI模型\n",
    "5，定义提示词模板\n",
    "6，创建Agent和Executor\n",
    "7,提问测试"
   ],
   "id": "b9395f2d416170aa"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 2、 React的模式",
   "id": "b711a2342b6d9ccd"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-05T06:34:57.916777Z",
     "start_time": "2025-08-05T06:34:52.421600Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from langchain_core.prompts import PromptTemplate\n",
    "from langchain_openai import ChatOpenAI\n",
    "import dotenv\n",
    "from langchain_core.tools import Tool\n",
    "import os\n",
    "#1、提供工具\n",
    "# 1.导入相关包\n",
    "from langchain.agents import AgentExecutor\n",
    "from langchain_community.tools.tavily_search import TavilySearchResults\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "from langchain.agents.react.agent import create_react_agent\n",
    "\n",
    "# 2.定义搜索化工具\n",
    "# ① 设置 TAVILY_API 密钥\n",
    "os.environ[\"TAVILY_API_KEY\"] = \"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\"  # 需要替换为你的 Tavily API 密钥\n",
    "\n",
    "# ② 定义搜索工具\n",
    "search = TavilySearchResults(max_results=1)\n",
    "search_tool = Tool(\n",
    "    name=\"search_tool\",\n",
    "    func=search.run,\n",
    "    description=\"用于互联网信息的检索\"\n",
    ")\n",
    "\n",
    "#2、提供工具集\n",
    "tools = [search_tool]\n",
    "\n",
    "#3、提供大模型\n",
    "dotenv.load_dotenv()\n",
    "\n",
    "os.environ['OPENAI_API_KEY'] = os.getenv(\"OPENAI_API_KEY\")\n",
    "os.environ['OPENAI_BASE_URL'] = os.getenv(\"OPENAI_BASE_URL\")\n",
    "llm = ChatOpenAI(\n",
    "    model=\"gpt-4o-mini\",\n",
    "    temperature=0,\n",
    ")\n",
    "#4、提供提示词模板 （明显相对于传统模式的区别）\n",
    "REACT_TEMPLATE = \"\"\"你是一个智能助手，可以访问以下工具：\n",
    "\n",
    "{tools}\n",
    "\n",
    "请严格按照以下格式响应：\n",
    "\n",
    "Question: 需要回答的输入问题\n",
    "Thought: 你应该始终思考要做什么\n",
    "Action: 要采取的行动，必须是[{tool_names}]中的一个\n",
    "Action Input: 行动的输入\n",
    "Observation: 行动的结果\n",
    "... (这个Thought/Action/Action Input/Observation可以重复N次)\n",
    "Thought: 我现在知道最终答案了\n",
    "Final Answer: 原始输入问题的最终答案\n",
    "\n",
    "当前问题: {input}\n",
    "{agent_scratchpad}\"\"\"\n",
    "\n",
    "prompt_template = PromptTemplate.from_template(REACT_TEMPLATE)\n",
    "\n",
    "agent = create_react_agent(\n",
    "    llm=llm,\n",
    "    tools=tools,\n",
    "    prompt=prompt_template,\n",
    ")\n",
    "\n",
    "#6、创建AgentExecutor\n",
    "agent_executor = AgentExecutor(\n",
    "    agent=agent,\n",
    "    tools=tools,\n",
    "    verbose=True,  #显示详情\n",
    "    max_iterations=3,#防止无限循环\n",
    "    early_stopping_method=\"generate\",#提前停止机制\n",
    "    handle_parsing_errors=True#错误恢复机制\n",
    ")\n",
    "\n",
    "#7、调用\n",
    "agent_executor.invoke({\"input\": \"明天北京的天气情况如何？\"})\n"
   ],
   "id": "4aed5fd266fd4b31",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001B[1m> Entering new AgentExecutor chain...\u001B[0m\n",
      "\u001B[32;1m\u001B[1;3mQuestion: 明天北京的天气情况如何？\n",
      "Thought: 我需要查找明天北京的天气预报。\n",
      "Action: search_tool\n",
      "Action Input: \"明天 北京 天气预报\"\u001B[0m\u001B[36;1m\u001B[1;3m[{'title': '中国气象局-天气预报- 北京', 'url': 'https://weather.cma.cn/web/weather/54511', 'content': '|  |  |  |  |  |  |  |  |  |\\n| --- | --- | --- | --- | --- | --- | --- | --- | --- |\\n| 时间 | 08:00 | 11:00 | 14:00 | 17:00 | 20:00 | 23:00 | 02:00 | 05:00 |\\n| 天气 |  |  |  |  |  |  |  |  |\\n| 气温 | 25.7℃ | 25.8℃ | 26.8℃ | 26.8℃ | 24℃ | 23.4℃ | 22.7℃ | 22.2℃ |\\n| 降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 | 2.3mm | 2.3mm | 2.3mm |\\n| 风速 | 3m/s | 2.3m/s | 2.6m/s | 3.3m/s | 1.9m/s | 3.3m/s | 2.6m/s | 2.4m/s |\\n| 风向 | 西南风 | 西南风 | 西南风 | 西南风 | 西南风 | 西南风 | 西南风 | 西南风 | [...] |  |  |  |  |  |  |  |  |  |\\n| --- | --- | --- | --- | --- | --- | --- | --- | --- |\\n| 时间 | 08:00 | 11:00 | 14:00 | 17:00 | 20:00 | 23:00 | 02:00 | 05:00 |\\n| 天气 |  |  |  |  |  |  |  |  |\\n| 气温 | 26.7℃ | 30.6℃ | 33.8℃ | 32.6℃ | 30.5℃ | 28.4℃ | 26.3℃ | 24.2℃ |\\n| 降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 |\\n| 风速 | 3.2m/s | 2.2m/s | 2.5m/s | 3.3m/s | 2.4m/s | 2.4m/s | 2.8m/s | 2.1m/s |\\n| 风向 | 西北风 | 东北风 | 西南风 | 西南风 | 西南风 | 西北风 | 东北风 | 东北风 | [...] |  |  |  |  |  |  |  |  |  |\\n| --- | --- | --- | --- | --- | --- | --- | --- | --- |\\n| 时间 | 08:00 | 11:00 | 14:00 | 17:00 | 20:00 | 23:00 | 02:00 | 05:00 |\\n| 天气 |  |  |  |  |  |  |  |  |\\n| 气温 | 24.3℃ | 26.2℃ | 28.8℃ | 28.4℃ | 26.4℃ | 25.7℃ | 23.8℃ | 23.2℃ |\\n| 降水 | 2.3mm | 2.3mm | 2.3mm | 2.3mm | 2.3mm | 2.3mm | 2.3mm | 2.3mm |\\n| 风速 | 3.3m/s | 3.3m/s | 3.2m/s | 3m/s | 2.8m/s | 3m/s | 2.6m/s | 2.5m/s |\\n| 风向 | 西北风 | 西南风 | 西南风 | 西南风 | 西南风 | 东南风 | 东南风 | 东北风 |', 'score': 0.7380092}]\u001B[0m\u001B[32;1m\u001B[1;3m我现在知道明天北京的天气情况了。  \n",
      "Final Answer: 明天北京的天气预报显示，气温将在24.3℃到33.8℃之间，预计无降水，风速在2.1m/s到3.3m/s之间，主要风向为西南风和西北风。\u001B[0m\n",
      "\n",
      "\u001B[1m> Finished chain.\u001B[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'input': '明天北京的天气情况如何？',\n",
       " 'output': '明天北京的天气预报显示，气温将在24.3℃到33.8℃之间，预计无降水，风速在2.1m/s到3.3m/s之间，主要风向为西南风和西北风。'}"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 10
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "##### 1，导入必要的库\n",
    "##### 2，定义搜索工具\n",
    "##### 3，准备工具列表\n",
    "##### 4，配置AI模型\n",
    "##### 5，定义提示词模板\n",
    "##### 6，创建REACT Agent .   create_react_agent 会分步思考\n",
    "##### 7，创建AgentExecutor\n",
    "##### 8 ,调用Agent ,向ai提问"
   ],
   "id": "efb07131d0268b37"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [],
   "execution_count": null,
   "source": "",
   "id": "1535fa279b898ddc"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    " React的模式:步骤清晰，把怎么想，怎么做，结果 一步步写出来\n",
    "\n",
    "\n",
    " Function_call模式：ai直接给答案，内部过程不可见"
   ],
   "id": "3e75c5af0b422b58"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
